/*
 * Copyright Jennifer West (?)
 */
package ij_plugins.debayer2sx;

import ij.ImageStack;
import ij.process.ImageProcessor;
import ij.process.ShortProcessor;

/**
 * Refactored from ImageJ plugin, Debayer_Image, provided by Jennifer West from University of Manitoba in 2006.
 * http://umanitoba.ca/faculties/science/astronomy/jwest/plugins.html
 *
 * Converted to be used as a library rather than a plugin.
 */
@SuppressWarnings("ALL")
public class Debayer1 {

    /**
     * Replication algorithm
     *
     * @param row_order 0 - "R-G-R-G", 1 - "B-G-B-G", 2 - "G-R-G-R", 2 - "G-B-G-B"
     * @param imp
     * @return
     */
    public static ImageStack replicate_decode(int row_order, ImageProcessor ip) {
        int width = ip.getWidth();
        int height = ip.getHeight();
        int one = 0;
        ImageStack rgb = new ImageStack(width, height, ip.getColorModel());
        ImageProcessor r = new ShortProcessor(width, height);
        ImageProcessor g = new ShortProcessor(width, height);
        ImageProcessor b = new ShortProcessor(width, height);
        //Short[] pixels = ip.getPixels();


        if (row_order == 0 || row_order == 1) {
            for (int y = 0; y < height; y += 2) {
                for (int x = 0; x < width; x += 2) {
                    one = ip.getPixel(x, y);
                    b.putPixel(x, y, one);
                    b.putPixel(x + 1, y, one);
                    b.putPixel(x, y + 1, one);
                    b.putPixel(x + 1, y + 1, one);
                }
            }

            for (int y = 1; y < height; y += 2) {
                for (int x = 1; x < width; x += 2) {
                    one = ip.getPixel(x, y);
                    r.putPixel(x, y, one);
                    r.putPixel(x + 1, y, one);
                    r.putPixel(x, y + 1, one);
                    r.putPixel(x + 1, y + 1, one);
                }
            }

            for (int y = 0; y < height; y += 2) {
                for (int x = 1; x < width; x += 2) {
                    one = ip.getPixel(x, y);
                    g.putPixel(x, y, one);
                    g.putPixel(x + 1, y, one);
                }
            }

            for (int y = 1; y < height; y += 2) {
                for (int x = 0; x < width; x += 2) {
                    one = ip.getPixel(x, y);
                    g.putPixel(x, y, one);
                    g.putPixel(x + 1, y, one);
                }
            }

            if (row_order == 0) {
                rgb.addSlice("red", b);
                rgb.addSlice("green", g);
                rgb.addSlice("blue", r);
            } else if (row_order == 1) {
                rgb.addSlice("red", r);
                rgb.addSlice("green", g);
                rgb.addSlice("blue", b);
            }
        } else if (row_order == 2 || row_order == 3) {
            for (int y = 1; y < height; y += 2) {
                for (int x = 0; x < width; x += 2) {
                    one = ip.getPixel(x, y);
                    b.putPixel(x, y, one);
                    b.putPixel(x + 1, y, one);
                    b.putPixel(x, y + 1, one);
                    b.putPixel(x + 1, y + 1, one);
                }
            }

            for (int y = 0; y < height; y += 2) {
                for (int x = 1; x < width; x += 2) {
                    one = ip.getPixel(x, y);
                    r.putPixel(x, y, one);
                    r.putPixel(x + 1, y, one);
                    r.putPixel(x, y + 1, one);
                    r.putPixel(x + 1, y + 1, one);
                }
            }

            for (int y = 0; y < height; y += 2) {
                for (int x = 0; x < width; x += 2) {
                    one = ip.getPixel(x, y);
                    g.putPixel(x, y, one);
                    g.putPixel(x + 1, y, one);
                }
            }

            for (int y = 1; y < height; y += 2) {
                for (int x = 1; x < width; x += 2) {
                    one = ip.getPixel(x, y);
                    g.putPixel(x, y, one);
                    g.putPixel(x + 1, y, one);
                }
            }

            if (row_order == 2) {
                rgb.addSlice("red", b);
                rgb.addSlice("green", g);
                rgb.addSlice("blue", r);
            } else if (row_order == 3) {
                rgb.addSlice("red", r);
                rgb.addSlice("green", g);
                rgb.addSlice("blue", b);
            }
        }

        return rgb;


    }

    /**
     * Bilinear algorithm
     *
     * @param row_order
     * @param imp
     * @return
     */
    public static ImageStack average_decode(int row_order, ImageProcessor ip) {
        int width = ip.getWidth();
        int height = ip.getHeight();

        int one = 0;
        int two = 0;
        int three = 0;
        int four = 0;
        ImageStack rgb = new ImageStack(width, height, ip.getColorModel());
        ImageProcessor r = new ShortProcessor(width, height);
        ImageProcessor g = new ShortProcessor(width, height);
        ImageProcessor b = new ShortProcessor(width, height);
        //Short[] pixels = ip.getPixels();


        if (row_order == 0 || row_order == 1) {
            for (int y = 0; y < height; y += 2) {
                for (int x = 0; x < width; x += 2) {
                    one = ip.getPixel(x, y);
                    two = ip.getPixel(x + 2, y);
                    three = ip.getPixel(x, y + 2);
                    four = ip.getPixel(x + 2, y + 2);

                    b.putPixel(x, y, one);
                    b.putPixel(x + 1, y, (one + two) / 2);
                    b.putPixel(x, y + 1, (one + three) / 2);
                    b.putPixel(x + 1, y + 1, (one + two + three + four) / 4);
                }
            }

            for (int y = 1; y < height; y += 2) {
                for (int x = 1; x < width; x += 2) {
                    one = ip.getPixel(x, y);
                    two = ip.getPixel(x + 2, y);
                    three = ip.getPixel(x, y + 2);
                    four = ip.getPixel(x + 2, y + 2);

                    r.putPixel(x, y, one);
                    r.putPixel(x + 1, y, (one + two) / 2);
                    r.putPixel(x, y + 1, (one + three) / 2);
                    r.putPixel(x + 1, y + 1, (one + two + three + four) / 4);
                }
            }

            for (int y = 0; y < height; y += 2) {
                for (int x = 1; x < width; x += 2) {
                    one = ip.getPixel(x, y);
                    two = ip.getPixel(x + 2, y);
                    three = ip.getPixel(x + 1, y + 1);
                    four = ip.getPixel(x + 1, y - 1);

                    g.putPixel(x, y, one);
                    g.putPixel(x + 1, y, (one + two + three + four) / 4);
                }
            }

            for (int y = 1; y < height; y += 2) {
                for (int x = 0; x < width; x += 2) {
                    one = ip.getPixel(x, y);
                    two = ip.getPixel(x + 2, y);
                    three = ip.getPixel(x + 1, y + 1);
                    four = ip.getPixel(x + 1, y - 1);

                    g.putPixel(x, y, one);
                    g.putPixel(x + 1, y, (one + two + three + four) / 4);
                }
            }

            if (row_order == 0) {
                rgb.addSlice("red", b);
                rgb.addSlice("green", g);
                rgb.addSlice("blue", r);
            } else if (row_order == 1) {
                rgb.addSlice("red", r);
                rgb.addSlice("green", g);
                rgb.addSlice("blue", b);
            }
        } else if (row_order == 2 || row_order == 3) {
            for (int y = 1; y < height; y += 2) {
                for (int x = 0; x < width; x += 2) {
                    one = ip.getPixel(x, y);
                    two = ip.getPixel(x + 2, y);
                    three = ip.getPixel(x, y + 2);
                    four = ip.getPixel(x + 2, y + 2);

                    b.putPixel(x, y, one);
                    b.putPixel(x + 1, y, (one + two) / 2);
                    b.putPixel(x, y + 1, (one + three) / 2);
                    b.putPixel(x + 1, y + 1, (one + two + three + four) / 4);
                }
            }

            for (int y = 0; y < height; y += 2) {
                for (int x = 1; x < width; x += 2) {
                    one = ip.getPixel(x, y);
                    two = ip.getPixel(x + 2, y);
                    three = ip.getPixel(x, y + 2);
                    four = ip.getPixel(x + 2, y + 2);

                    r.putPixel(x, y, one);
                    r.putPixel(x + 1, y, (one + two) / 2);
                    r.putPixel(x, y + 1, (one + three) / 2);
                    r.putPixel(x + 1, y + 1, (one + two + three + four) / 4);
                }
            }

            for (int y = 0; y < height; y += 2) {
                for (int x = 0; x < width; x += 2) {
                    one = ip.getPixel(x, y);
                    two = ip.getPixel(x + 2, y);
                    three = ip.getPixel(x + 1, y + 1);
                    four = ip.getPixel(x + 1, y - 1);

                    g.putPixel(x, y, one);
                    g.putPixel(x + 1, y, (one + two + three + four) / 4);
                }
            }

            for (int y = 1; y < height; y += 2) {
                for (int x = 1; x < width; x += 2) {
                    one = ip.getPixel(x, y);
                    two = ip.getPixel(x + 2, y);
                    three = ip.getPixel(x + 1, y + 1);
                    four = ip.getPixel(x + 1, y - 1);

                    g.putPixel(x, y, one);
                    g.putPixel(x + 1, y, (one + two + three + four) / 4);
                }
            }

            if (row_order == 2) {
                rgb.addSlice("red", b);
                rgb.addSlice("green", g);
                rgb.addSlice("blue", r);
            } else if (row_order == 3) {
                rgb.addSlice("red", r);
                rgb.addSlice("green", g);
                rgb.addSlice("blue", b);
            }
        }

        return rgb;


    }

    /**
     * Smooth Hue algorithm
     *
     * @param row_order
     * @param imp
     * @return
     */
    public static ImageStack smooth_decode(int row_order, ImageProcessor ip) {
        int width = ip.getWidth();
        int height = ip.getHeight();
        double G1 = 0;
        double G2 = 0;
        double G3 = 0;
        double G4 = 0;
        double G5 = 0;
        double G6 = 0;
        double G7 = 0;
        double G8 = 0;
        double G9 = 0;
        double B1 = 0;
        double B2 = 0;
        double B3 = 0;
        double B4 = 0;
        double R1 = 0;
        double R2 = 0;
        double R3 = 0;
        double R4 = 0;
        ImageStack rgb = new ImageStack(width, height, ip.getColorModel());
        ImageProcessor r = new ShortProcessor(width, height);
        ImageProcessor g = new ShortProcessor(width, height);
        ImageProcessor b = new ShortProcessor(width, height);
        //Short[] pixels = ip.getPixels();


        if (row_order == 0 || row_order == 1) {
            //Solve for green pixels first
            for (int y = 0; y < height; y += 2) {
                for (int x = 1; x < width; x += 2) {
                    G1 = ip.getPixel(x, y);
                    G2 = ip.getPixel(x + 2, y);
                    G3 = ip.getPixel(x + 1, y + 1);
                    G4 = ip.getPixel(x + 1, y - 1);

                    g.putPixel(x, y, (int) G1);
                    if (y == 0) g.putPixel(x + 1, y, (int) ((G1 + G2 + G3) / 3));
                    else g.putPixel(x + 1, y, (int) ((G1 + G2 + G3 + G4) / 4));
                    if (x == 1) g.putPixel(x - 1, y, (int) ((G1 + G4 + ip.getPixel(x - 1, y + 1)) / 3));
                }
            }

            for (int x = 0; x < width; x += 2) {
                for (int y = 1; y < height; y += 2) {

                    G1 = ip.getPixel(x, y);
                    G2 = ip.getPixel(x + 2, y);
                    G3 = ip.getPixel(x + 1, y + 1);
                    G4 = ip.getPixel(x + 1, y - 1);

                    g.putPixel(x, y, (int) G1);
                    if (x == 0) g.putPixel(x + 1, y, (int) ((G1 + G2 + G3) / 3));
                    else g.putPixel(x + 1, y, (int) ((G1 + G2 + G3 + G4) / 4));
                }
            }

            g.putPixel(0, 0, (ip.getPixel(0, 1) + ip.getPixel(1, 0)) / 2);


            for (int y = 0; y < height; y += 2) {
                for (int x = 0; x < width; x += 2) {
                    B1 = ip.getPixel(x, y);
                    B2 = ip.getPixel(x + 2, y);
                    B3 = ip.getPixel(x, y + 2);
                    B4 = ip.getPixel(x + 2, y + 2);
                    G1 = g.getPixel(x, y);
                    G2 = g.getPixel(x + 2, y);
                    G3 = g.getPixel(x, y + 2);
                    G4 = g.getPixel(x + 2, y + 2);
                    G5 = g.getPixel(x + 1, y);
                    G6 = g.getPixel(x, y + 1);
                    G9 = g.getPixel(x + 1, y + 1);
                    if (G1 == 0) G1 = 1;
                    if (G2 == 0) G2 = 1;
                    if (G3 == 0) G3 = 1;
                    if (G4 == 0) G4 = 1;

                    b.putPixel(x, y, (int) (B1));
                    b.putPixel(x + 1, y, (int) ((G5 / 2 * ((B1 / G1) + (B2 / G2)))));
                    b.putPixel(x, y + 1, (int) ((G6 / 2 * ((B1 / G1) + (B3 / G3)))));
                    b.putPixel(x + 1, y + 1, (int) ((G9 / 4 * ((B1 / G1) + (B3 / G3) + (B2 / G2) + (B4 / G4)))));

                }
            }

            for (int y = 1; y < height; y += 2) {
                for (int x = 1; x < width; x += 2) {
                    R1 = ip.getPixel(x, y);
                    R2 = ip.getPixel(x + 2, y);
                    R3 = ip.getPixel(x, y + 2);
                    R4 = ip.getPixel(x + 2, y + 2);
                    G1 = g.getPixel(x, y);
                    G2 = g.getPixel(x + 2, y);
                    G3 = g.getPixel(x, y + 2);
                    G4 = g.getPixel(x + 2, y + 2);
                    G5 = g.getPixel(x + 1, y);
                    G6 = g.getPixel(x, y + 1);
                    G9 = g.getPixel(x + 1, y + 1);
                    if (G1 == 0) G1 = 1;
                    if (G2 == 0) G2 = 1;
                    if (G3 == 0) G3 = 1;
                    if (G4 == 0) G4 = 1;

                    r.putPixel(x, y, (int) (R1));
                    r.putPixel(x + 1, y, (int) ((G5 / 2 * ((R1 / G1) + (R2 / G2)))));
                    r.putPixel(x, y + 1, (int) ((G6 / 2 * ((R1 / G1) + (R3 / G3)))));
                    r.putPixel(x + 1, y + 1, (int) ((G9 / 4 * ((R1 / G1) + (R3 / G3) + (R2 / G2) + (R4 / G4)))));
                }
            }


            if (row_order == 0) {
                rgb.addSlice("red", b);
                rgb.addSlice("green", g);
                rgb.addSlice("blue", r);
            } else if (row_order == 1) {
                rgb.addSlice("red", r);
                rgb.addSlice("green", g);
                rgb.addSlice("blue", b);
            }
        } else if (row_order == 2 || row_order == 3) {

            for (int y = 0; y < height; y += 2) {
                for (int x = 0; x < width; x += 2) {
                    G1 = ip.getPixel(x, y);
                    G2 = ip.getPixel(x + 2, y);
                    G3 = ip.getPixel(x + 1, y + 1);
                    G4 = ip.getPixel(x + 1, y - 1);

                    g.putPixel(x, y, (int) G1);
                    if (y == 0) g.putPixel(x + 1, y, (int) ((G1 + G2 + G3) / 3));
                    else g.putPixel(x + 1, y, (int) ((G1 + G2 + G3 + G4) / 4));
                    if (x == 1) g.putPixel(x - 1, y, (int) ((G1 + G4 + ip.getPixel(x - 1, y + 1)) / 3));
                }
            }

            for (int y = 1; y < height; y += 2) {
                for (int x = 1; x < width; x += 2) {
                    G1 = ip.getPixel(x, y);
                    G2 = ip.getPixel(x + 2, y);
                    G3 = ip.getPixel(x + 1, y + 1);
                    G4 = ip.getPixel(x + 1, y - 1);

                    g.putPixel(x, y, (int) G1);
                    if (x == 0) g.putPixel(x + 1, y, (int) ((G1 + G2 + G3) / 3));
                    else g.putPixel(x + 1, y, (int) ((G1 + G2 + G3 + G4) / 4));
                }
            }

            g.putPixel(0, 0, (ip.getPixel(0, 1) + ip.getPixel(1, 0)) / 2);

            for (int y = 1; y < height; y += 2) {
                for (int x = 0; x < width; x += 2) {
                    B1 = ip.getPixel(x, y);
                    B2 = ip.getPixel(x + 2, y);
                    B3 = ip.getPixel(x, y + 2);
                    B4 = ip.getPixel(x + 2, y + 2);
                    G1 = g.getPixel(x, y);
                    G2 = g.getPixel(x + 2, y);
                    G3 = g.getPixel(x, y + 2);
                    G4 = g.getPixel(x + 2, y + 2);
                    G5 = g.getPixel(x + 1, y);
                    G6 = g.getPixel(x, y + 1);
                    G9 = g.getPixel(x + 1, y + 1);
                    if (G1 == 0) G1 = 1;
                    if (G2 == 0) G2 = 1;
                    if (G3 == 0) G3 = 1;
                    if (G4 == 0) G4 = 1;

                    b.putPixel(x, y, (int) (B1));
                    b.putPixel(x + 1, y, (int) ((G5 / 2 * ((B1 / G1) + (B2 / G2)))));
                    b.putPixel(x, y + 1, (int) ((G6 / 2 * ((B1 / G1) + (B3 / G3)))));
                    b.putPixel(x + 1, y + 1, (int) ((G9 / 4 * ((B1 / G1) + (B3 / G3) + (B2 / G2) + (B4 / G4)))));

                }
            }

            for (int y = 0; y < height; y += 2) {
                for (int x = 1; x < width; x += 2) {
                    R1 = ip.getPixel(x, y);
                    R2 = ip.getPixel(x + 2, y);
                    R3 = ip.getPixel(x, y + 2);
                    R4 = ip.getPixel(x + 2, y + 2);
                    G1 = g.getPixel(x, y);
                    G2 = g.getPixel(x + 2, y);
                    G3 = g.getPixel(x, y + 2);
                    G4 = g.getPixel(x + 2, y + 2);
                    G5 = g.getPixel(x + 1, y);
                    G6 = g.getPixel(x, y + 1);
                    G9 = g.getPixel(x + 1, y + 1);
                    if (G1 == 0) G1 = 1;
                    if (G2 == 0) G2 = 1;
                    if (G3 == 0) G3 = 1;
                    if (G4 == 0) G4 = 1;

                    r.putPixel(x, y, (int) (R1));
                    r.putPixel(x + 1, y, (int) ((G5 / 2 * ((R1 / G1) + (R2 / G2)))));
                    r.putPixel(x, y + 1, (int) ((G6 / 2 * ((R1 / G1) + (R3 / G3)))));
                    r.putPixel(x + 1, y + 1, (int) ((G9 / 4 * ((R1 / G1) + (R3 / G3) + (R2 / G2) + (R4 / G4)))));
                }
            }


            if (row_order == 2) {
                rgb.addSlice("red", b);
                rgb.addSlice("green", g);
                rgb.addSlice("blue", r);
            } else if (row_order == 3) {
                rgb.addSlice("red", r);
                rgb.addSlice("green", g);
                rgb.addSlice("blue", b);
            }
        }

        return rgb;


    }


    public static ImageStack adaptive_decode(int row_order, ImageProcessor ip) {
        //Adaptive Smooth Hue algorithm (Edge detecting)
        int width = ip.getWidth();
        int height = ip.getHeight();
        double G1 = 0;
        double G2 = 0;
        double G3 = 0;
        double G4 = 0;
        double G5 = 0;
        double G6 = 0;
        double G7 = 0;
        double G8 = 0;
        double G9 = 0;
        double B1 = 0;
        double B2 = 0;
        double B3 = 0;
        double B4 = 0;
        double B5 = 0;
        double R1 = 0;
        double R2 = 0;
        double R3 = 0;
        double R4 = 0;
        double R5 = 0;
        double N = 0;
        double S = 0;
        double E = 0;
        double W = 0;
        ImageStack rgb = new ImageStack(width, height, ip.getColorModel());
        ImageProcessor r = new ShortProcessor(width, height);
        ImageProcessor g = new ShortProcessor(width, height);
        ImageProcessor b = new ShortProcessor(width, height);
        //Short[] pixels = ip.getPixels();


        if (row_order == 0 || row_order == 1) {
            //Solve for green pixels first
            for (int y = 0; y < height; y += 2) {
                for (int x = 1; x < width; x += 2) {
                    G1 = ip.getPixel(x, y);
                    G2 = ip.getPixel(x + 2, y);
                    G3 = ip.getPixel(x + 1, y + 1);
                    G4 = ip.getPixel(x + 1, y - 1);
                    R1 = ip.getPixel(x - 1, y);
                    R2 = ip.getPixel(x + 3, y);
                    R3 = ip.getPixel(x + 1, y + 2);
                    R4 = ip.getPixel(x + 1, y - 2);
                    R5 = ip.getPixel(x + 1, y + 1);

                    N = Math.abs(R4 - R5) * 2 + Math.abs(G4 - G3);
                    S = Math.abs(R5 - R3) * 2 + Math.abs(G4 - G3);
                    E = Math.abs(R5 - R2) * 2 + Math.abs(G1 - G2);
                    W = Math.abs(R1 - R5) * 2 + Math.abs(G1 - G2);

                    if (N < S && N < E && N < W) {
                        g.putPixel(x + 1, y, (int) ((G4 * 3 + R5 + G3 - R4) / 4));
                    } else if (S < N && S < E && S < W) {
                        g.putPixel(x + 1, y, (int) ((G3 * 3 + R5 + G4 - R3) / 4));
                    } else if (W < N && W < E && W < S) {
                        g.putPixel(x + 1, y, (int) ((G1 * 3 + R5 + G2 - R1) / 4));
                    } else if (E < N && E < S && E < W) {
                        g.putPixel(x + 1, y, (int) ((G2 * 3 + R5 + G1 - R2) / 4));
                    }

                    g.putPixel(x, y, (int) G1);

                    if (y == 0) g.putPixel(x + 1, y, (int) ((G1 + G2 + G3) / 3));
                    else g.putPixel(x + 1, y, (int) ((G1 + G2 + G3 + G4) / 4));
                    if (x == 1) g.putPixel(x - 1, y, (int) ((G1 + G4 + ip.getPixel(x - 1, y + 1)) / 3));
                }
            }

            for (int x = 0; x < width; x += 2) {
                for (int y = 1; y < height; y += 2) {
                    G1 = ip.getPixel(x, y);
                    G2 = ip.getPixel(x + 2, y);
                    G3 = ip.getPixel(x + 1, y + 1);
                    G4 = ip.getPixel(x + 1, y - 1);
                    R1 = ip.getPixel(x - 1, y);
                    R2 = ip.getPixel(x + 3, y);
                    R3 = ip.getPixel(x + 1, y + 2);
                    R4 = ip.getPixel(x + 1, y - 2);
                    R5 = ip.getPixel(x + 1, y + 1);

                    N = Math.abs(R4 - R5) * 2 + Math.abs(G4 - G3);
                    S = Math.abs(R5 - R3) * 2 + Math.abs(G4 - G3);
                    E = Math.abs(R5 - R2) * 2 + Math.abs(G1 - G2);
                    W = Math.abs(R1 - R5) * 2 + Math.abs(G1 - G2);

                    if (N < S && N < E && N < W) {
                        g.putPixel(x + 1, y, (int) ((G4 * 3 + R5 + G3 - R4) / 4));
                    } else if (S < N && S < E && S < W) {
                        g.putPixel(x + 1, y, (int) ((G3 * 3 + R5 + G4 - R3) / 4));
                    } else if (W < N && W < E && W < S) {
                        g.putPixel(x + 1, y, (int) ((G1 * 3 + R5 + G2 - R1) / 4));
                    } else if (E < N && E < S && E < W) {
                        g.putPixel(x + 1, y, (int) ((G2 * 3 + R5 + G1 - R2) / 4));
                    }

                    g.putPixel(x, y, (int) G1);
                    if (x == 0) g.putPixel(x + 1, y, (int) ((G1 + G2 + G3) / 3));
                    else g.putPixel(x + 1, y, (int) ((G1 + G2 + G3 + G4) / 4));
                }
            }

            g.putPixel(0, 0, (ip.getPixel(0, 1) + ip.getPixel(1, 0)) / 2);

            for (int y = 0; y < height; y += 2) {
                for (int x = 0; x < width; x += 2) {
                    B1 = ip.getPixel(x, y);
                    B2 = ip.getPixel(x + 2, y);
                    B3 = ip.getPixel(x, y + 2);
                    B4 = ip.getPixel(x + 2, y + 2);
                    G1 = g.getPixel(x, y);
                    G2 = g.getPixel(x + 2, y);
                    G3 = g.getPixel(x, y + 2);
                    G4 = g.getPixel(x + 2, y + 2);
                    G5 = g.getPixel(x + 1, y);
                    G6 = g.getPixel(x, y + 1);
                    G9 = g.getPixel(x + 1, y + 1);
                    if (G1 == 0) G1 = 1;
                    if (G2 == 0) G2 = 1;
                    if (G3 == 0) G3 = 1;
                    if (G4 == 0) G4 = 1;

                    b.putPixel(x, y, (int) (B1));
                    b.putPixel(x + 1, y, (int) ((G5 / 2 * ((B1 / G1) + (B2 / G2)))));
                    b.putPixel(x, y + 1, (int) ((G6 / 2 * ((B1 / G1) + (B3 / G3)))));
                    b.putPixel(x + 1, y + 1, (int) ((G9 / 4 * ((B1 / G1) + (B3 / G3) + (B2 / G2) + (B4 / G4)))));

                }
            }

            for (int y = 1; y < height; y += 2) {
                for (int x = 1; x < width; x += 2) {
                    R1 = ip.getPixel(x, y);
                    R2 = ip.getPixel(x + 2, y);
                    R3 = ip.getPixel(x, y + 2);
                    R4 = ip.getPixel(x + 2, y + 2);
                    G1 = g.getPixel(x, y);
                    G2 = g.getPixel(x + 2, y);
                    G3 = g.getPixel(x, y + 2);
                    G4 = g.getPixel(x + 2, y + 2);
                    G5 = g.getPixel(x + 1, y);
                    G6 = g.getPixel(x, y + 1);
                    G9 = g.getPixel(x + 1, y + 1);
                    if (G1 == 0) G1 = 1;
                    if (G2 == 0) G2 = 1;
                    if (G3 == 0) G3 = 1;
                    if (G4 == 0) G4 = 1;

                    r.putPixel(x, y, (int) (R1));
                    r.putPixel(x + 1, y, (int) ((G5 / 2 * ((R1 / G1) + (R2 / G2)))));
                    r.putPixel(x, y + 1, (int) ((G6 / 2 * ((R1 / G1) + (R3 / G3)))));
                    r.putPixel(x + 1, y + 1, (int) ((G9 / 4 * ((R1 / G1) + (R3 / G3) + (R2 / G2) + (R4 / G4)))));
                }
            }


            if (row_order == 0) {
                rgb.addSlice("red", b);
                rgb.addSlice("green", g);
                rgb.addSlice("blue", r);
            } else if (row_order == 1) {
                rgb.addSlice("red", r);
                rgb.addSlice("green", g);
                rgb.addSlice("blue", b);
            }
        } else if (row_order == 2 || row_order == 3) {

            for (int y = 0; y < height; y += 2) {
                for (int x = 0; x < width; x += 2) {
                    G1 = ip.getPixel(x, y);
                    G2 = ip.getPixel(x + 2, y);
                    G3 = ip.getPixel(x + 1, y + 1);
                    G4 = ip.getPixel(x + 1, y - 1);
                    R1 = ip.getPixel(x - 1, y);
                    R2 = ip.getPixel(x + 3, y);
                    R3 = ip.getPixel(x + 1, y + 2);
                    R4 = ip.getPixel(x + 1, y - 2);
                    R5 = ip.getPixel(x + 1, y + 1);

                    N = Math.abs(R4 - R5) * 2 + Math.abs(G4 - G3);
                    S = Math.abs(R5 - R3) * 2 + Math.abs(G4 - G3);
                    E = Math.abs(R5 - R2) * 2 + Math.abs(G1 - G2);
                    W = Math.abs(R1 - R5) * 2 + Math.abs(G1 - G2);

                    if (N < S && N < E && N < W) {
                        g.putPixel(x + 1, y, (int) ((G4 * 3 + R5 + G3 - R4) / 4));
                    } else if (S < N && S < E && S < W) {
                        g.putPixel(x + 1, y, (int) ((G3 * 3 + R5 + G4 - R3) / 4));
                    } else if (W < N && W < E && W < S) {
                        g.putPixel(x + 1, y, (int) ((G1 * 3 + R5 + G2 - R1) / 4));
                    } else if (E < N && E < S && E < W) {
                        g.putPixel(x + 1, y, (int) ((G2 * 3 + R5 + G1 - R2) / 4));
                    }

                    g.putPixel(x, y, (int) G1);
                    if (y == 0) g.putPixel(x + 1, y, (int) ((G1 + G2 + G3) / 3));
                    else g.putPixel(x + 1, y, (int) ((G1 + G2 + G3 + G4) / 4));
                    if (x == 1) g.putPixel(x - 1, y, (int) ((G1 + G4 + ip.getPixel(x - 1, y + 1)) / 3));
                }
            }

            for (int y = 1; y < height; y += 2) {
                for (int x = 1; x < width; x += 2) {
                    G1 = ip.getPixel(x, y);
                    G2 = ip.getPixel(x + 2, y);
                    G3 = ip.getPixel(x + 1, y + 1);
                    G4 = ip.getPixel(x + 1, y - 1);
                    R1 = ip.getPixel(x - 1, y);
                    R2 = ip.getPixel(x + 3, y);
                    R3 = ip.getPixel(x + 1, y + 2);
                    R4 = ip.getPixel(x + 1, y - 2);
                    R5 = ip.getPixel(x + 1, y + 1);

                    N = Math.abs(R4 - R5) * 2 + Math.abs(G4 - G3);
                    S = Math.abs(R5 - R3) * 2 + Math.abs(G4 - G3);
                    E = Math.abs(R5 - R2) * 2 + Math.abs(G1 - G2);
                    W = Math.abs(R1 - R5) * 2 + Math.abs(G1 - G2);

                    if (N < S && N < E && N < W) {
                        g.putPixel(x + 1, y, (int) ((G4 * 3 + R5 + G3 - R4) / 4));
                    } else if (S < N && S < E && S < W) {
                        g.putPixel(x + 1, y, (int) ((G3 * 3 + R5 + G4 - R3) / 4));
                    } else if (W < N && W < E && W < S) {
                        g.putPixel(x + 1, y, (int) ((G1 * 3 + R5 + G2 - R1) / 4));
                    } else if (E < N && E < S && E < W) {
                        g.putPixel(x + 1, y, (int) ((G2 * 3 + R5 + G1 - R2) / 4));
                    }

                    g.putPixel(x, y, (int) G1);
                    if (x == 0) g.putPixel(x + 1, y, (int) ((G1 + G2 + G3) / 3));
                    else g.putPixel(x + 1, y, (int) ((G1 + G2 + G3 + G4) / 4));
                }
            }

            g.putPixel(0, 0, (ip.getPixel(0, 1) + ip.getPixel(1, 0)) / 2);

            for (int y = 1; y < height; y += 2) {
                for (int x = 0; x < width; x += 2) {
                    B1 = ip.getPixel(x, y);
                    B2 = ip.getPixel(x + 2, y);
                    B3 = ip.getPixel(x, y + 2);
                    B4 = ip.getPixel(x + 2, y + 2);
                    G1 = g.getPixel(x, y);
                    G2 = g.getPixel(x + 2, y);
                    G3 = g.getPixel(x, y + 2);
                    G4 = g.getPixel(x + 2, y + 2);
                    G5 = g.getPixel(x + 1, y);
                    G6 = g.getPixel(x, y + 1);
                    G9 = g.getPixel(x + 1, y + 1);
                    if (G1 == 0) G1 = 1;
                    if (G2 == 0) G2 = 1;
                    if (G3 == 0) G3 = 1;
                    if (G4 == 0) G4 = 1;

                    b.putPixel(x, y, (int) (B1));
                    b.putPixel(x + 1, y, (int) ((G5 / 2 * ((B1 / G1) + (B2 / G2)))));
                    b.putPixel(x, y + 1, (int) ((G6 / 2 * ((B1 / G1) + (B3 / G3)))));
                    b.putPixel(x + 1, y + 1, (int) ((G9 / 4 * ((B1 / G1) + (B3 / G3) + (B2 / G2) + (B4 / G4)))));
                }
            }

            for (int y = 0; y < height; y += 2) {
                for (int x = 1; x < width; x += 2) {
                    R1 = ip.getPixel(x, y);
                    R2 = ip.getPixel(x + 2, y);
                    R3 = ip.getPixel(x, y + 2);
                    R4 = ip.getPixel(x + 2, y + 2);
                    G1 = g.getPixel(x, y);
                    G2 = g.getPixel(x + 2, y);
                    G3 = g.getPixel(x, y + 2);
                    G4 = g.getPixel(x + 2, y + 2);
                    G5 = g.getPixel(x + 1, y);
                    G6 = g.getPixel(x, y + 1);
                    G9 = g.getPixel(x + 1, y + 1);
                    if (G1 == 0) G1 = 1;
                    if (G2 == 0) G2 = 1;
                    if (G3 == 0) G3 = 1;
                    if (G4 == 0) G4 = 1;

                    r.putPixel(x, y, (int) (R1));
                    r.putPixel(x + 1, y, (int) ((G5 / 2 * ((R1 / G1) + (R2 / G2)))));
                    r.putPixel(x, y + 1, (int) ((G6 / 2 * ((R1 / G1) + (R3 / G3)))));
                    r.putPixel(x + 1, y + 1, (int) ((G9 / 4 * ((R1 / G1) + (R3 / G3) + (R2 / G2) + (R4 / G4)))));
                }
            }


            if (row_order == 2) {
                rgb.addSlice("red", b);
                rgb.addSlice("green", g);
                rgb.addSlice("blue", r);
            } else if (row_order == 3) {
                rgb.addSlice("red", r);
                rgb.addSlice("green", g);
                rgb.addSlice("blue", b);
            }
        }

        return rgb;

    }

}	

